home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '90 / MacHack'90 Proceedings / John Norstad / Reusable Code / Source / cvrt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-10  |  24.7 KB  |  926 lines  |  [TEXT/MPS ]

  1. /*______________________________________________________________________
  2.  
  3.     cvrt.c - Tool to Convert a Text File to a Sequence of STR# Resources.
  4.     
  5.     Copyright © 1988, 1989, 1990 Northwestern University.  Permission is 
  6.     granted to use this code in your own projects, provided you give credit 
  7.     to both John Norstad and Northwestern University in your about box or 
  8.     document.
  9.     
  10.     This tool is used to prepare text for the report module rep.c
  11.     and the help module hlp.c.
  12.     
  13.     When preparing type 1 reports for the report module rep.c, the wrap tool
  14.     should be run first (with the -p option), then the output of wrap should 
  15.     be processed by cvrt.
  16.     
  17.     cvrt -o file1 -i nnn [-t aaa] [-g bbb] [-c ccc]
  18.         [-p file2 -h xxx -w yyy] [file3]
  19.     
  20.     file1 = output resource file.
  21.     nnn = starting STR# resource id.
  22.     aaa = TCON resource id.
  23.     bbb = TAG resource id.
  24.     ccc = CELL resource id.
  25.     file2 = pict resource file.
  26.     xxx = height of report cells in pixels.
  27.     yyy = width of report cells in pixels.
  28.     file3 = input text file.
  29.     
  30.     The text file is converted to a consecutive sequence of STR# 
  31.     resources starting with id nnn.
  32.     
  33.     The source text is intermixed with special cvrt directives.  Any line 
  34.     starting with the character "\" is treated as a directive.  Directives
  35.     must be all lower case.  The syntax checking by this tool is minimal.
  36.     
  37.     \str#
  38.     
  39.         Starts a new STR# resource.
  40.     
  41.     \tcon title
  42.     
  43.         Table of contents entry.  The title and the current line number
  44.         (zero based) are saved in the TCON resource.
  45.         
  46.     \tag nnn
  47.     
  48.         Tag resource entry.  The number nnn and the current line number
  49.         (zero based) are saved in the TAG resource.
  50.         
  51.     \style xxx xxx xxx
  52.  
  53.         The next text line is drawn in the specified style or styles.  xxx may
  54.         be any of the following:
  55.         
  56.         normal    (default)
  57.         bold
  58.         italic
  59.         underline
  60.         outline
  61.         shadow
  62.         condense
  63.         extend
  64.         
  65.     \just xxx
  66.     
  67.         The next text line or picture is drawn with the specified justification.
  68.         xxx may be any of the following:
  69.         
  70.         left        (default for text lines)
  71.         center    (default for pictures)
  72.         right
  73.         
  74.     \size xxx
  75.     
  76.         Print the following line of text xxx% larger than normal.  Printing
  77.         only.  The normal font size is multiplied by xxx%, then truncated.  
  78.         For non-laserwriters it is then rounded down to the nearest font
  79.         size which can be printed without Font Manager scaling. 
  80.         
  81.     \only xxx xxx
  82.     
  83.         The next text line or picture or table of contents entry should only 
  84.         be output as specified.  xxx may be any of the following:
  85.         
  86.         screen    Only in the report on the screen.
  87.         print        Only in the printed document.
  88.         save        Only in the saved document.
  89.         
  90.         The default for text lines is: screen print save
  91.         The default for pictures is: screen print
  92.         The default for tcon entries is: screen print
  93.     
  94.     \pict id
  95.     
  96.         A picture from the pict resource file should be inserted at this point.
  97.         "id" is the resource id of the pict.
  98.         
  99.     \page nnn
  100.     
  101.         Start a new page.  Printing only.  The parameter nnn is optional.
  102.         nnn = 0: Do not put a header on this or subsequent pages.
  103.         nnn > 0: Put a header on this and subsequent pages, and start page 
  104.             numbering on this page with nnn.
  105.         default: Put a header on this and subsequent pages, and increment
  106.             page numbers by 1.
  107.         
  108.     \keep
  109.     
  110.         Keep the following block of text on the same page.  Force a page
  111.         break if necessary.  Printing only.  Paragraphs are always kept
  112.         on a page, never split across page boundaries.
  113.         
  114.     \endkeep
  115.     
  116.         End a keep block.  Printing only.
  117.         
  118.     \itcon xspace
  119.     
  120.         Insert table of contents.  Printing only.
  121.         
  122.         xspace = extra space between lines, in 1/100 inch.
  123.         
  124.     Some of the  directives above cause escape sequences to be generated at 
  125.     the beginnings of lines in the STR# resources.  These escape sequences 
  126.     have the following common format:
  127.     
  128.         byte 0 = escape code = a small number less than 31.
  129.         byte 1 = number of bytes in the escape sequence.
  130.         remaining bytes = parameters.
  131.         
  132.     The following escape sequences are used:
  133.     
  134.     Style:
  135.     
  136.         byte 0 = docStyle = 0
  137.         byte 1 = 3
  138.         byte 2 = style
  139.         
  140.     Justification:
  141.     
  142.         byte 0 = docJust = 1
  143.         byte 1 = 3
  144.         byte 2 = justification:
  145.             0 = Left
  146.             1 = Center
  147.             2 = Right
  148.             
  149.     Size:
  150.     
  151.         byte 0 = docSize = 2
  152.         byte 1 = 4
  153.         bytes 2,3 = percent size change
  154.             
  155.     Only:
  156.     
  157.         byte 0 = docOnly = 3
  158.         byte 1 = 3
  159.         byte 2 = flags
  160.             bit 0 = Screen
  161.             bit 1 = Print
  162.             bit 2 = Save
  163.             
  164.     Pict:
  165.     
  166.         byte 0 = docPict = 4
  167.         byte 1 = 6
  168.         bytes 2,3 = PICT resource id
  169.         bytes 4,5 = band number
  170.         
  171.         For pictures multiple lines are output to the STR# resource, each
  172.         in the format above.  Enough lines are output to completely cover
  173.         the picture in hands of of the same height as the cell height.
  174.         Pictures wider than the (cell width - 8) are scaled so that their
  175.         width is exactly (cell width - 8). The band numbers in the escape 
  176.         sequences increment from 0 to number of bands - 1.
  177.  
  178.     The remaining escape sequences are only used for printing, and they always
  179.     occur on lines by themselves, preceded by on "Only" escape sequence that 
  180.     says the line only applies to printing.
  181.         
  182.     Page:
  183.     
  184.         byte 0 = docPage = 5
  185.         byte 1 = 4
  186.         bytes 2,3 = page number, or 0xffff if none specified
  187.         
  188.     Keep:
  189.     
  190.         byte 0 = docKeep = 6
  191.         byte 1 = 2
  192.         
  193.     EndKeep:
  194.     
  195.         byte 0 = docEndKeep = 7
  196.         byte 1 = 2
  197.         
  198.     ITcon:
  199.     
  200.         byte 0 = docITcon = 8
  201.         byte 1 = 4
  202.         bytes 2,3 = extra space
  203.         
  204.     There is one other special escape code, the end-of-paragraph escape
  205.     code 31.  This escape code is not inserted by cvrt, but by the wrap
  206.     tool.  It marks ends of paragraphs.  The printing code in rep.c uses
  207.     these codes when rewrapping paragraphs to new margins.
  208.     
  209.     The TCON resource, if one is generated, has the following format
  210.     (using Rez syntax):
  211.     
  212.     type 'TCON' {
  213.         integer = $$CountOf(list);
  214.         array list {
  215.             integer;                { line number for online doc }
  216.             byte;                    { only code - docScreen, docPrint, or 
  217.                                         docScreen | docPrint }
  218.             pstring;                { table of contents entry }
  219.             align word;
  220.         };
  221.     }
  222.     
  223.     The TAG resource, if one is generated, has the following format
  224.     (using Rez syntax):
  225.     
  226.     type 'TAG ' {
  227.         integer = $$CountOf(list);
  228.         array list {
  229.             integer;                { line number }
  230.             integer;                { tag }
  231.         };
  232.     }
  233.     
  234.     The CELL resource, if one is generated, contains one entry per
  235.     screen line, in the following format (using Rez syntax):
  236.     
  237.     type 'CELL' {
  238.         array list {
  239.             byte;                    { ordinal of STR# resource containing line }
  240.             integer;                { offset in STR# of line }
  241.         };
  242.     }
  243.     
  244.     CELL resources must be generated for type 1 reports.  The CELL resource
  245.     becomes the "cell array" in the list manager data structure for the 
  246.     report (see rep.c).  Prebuilding this array here in cvrt speeds up the
  247.     initialization of large type 1 reports.
  248. _____________________________________________________________________*/
  249.  
  250. #pragma load "precompile"
  251. #include "doc.h"
  252.  
  253. unsigned char    *p;                /* pointer to cur pos in STR# rsrc */
  254.  
  255. void putOnlyPrint (void)
  256.  
  257. {
  258.     *p++ = docOnly;
  259.     *p++ = 3;
  260.     *p++ = docPrint;
  261. };
  262.  
  263. short main(int argc, char *argv[])
  264.  
  265. {
  266.     short                i;                        /* loop index */
  267.     Boolean            inFileSpecified = false;    
  268.     Boolean            outFileSpecified = false; 
  269.     Boolean            idSpecified = false;        
  270.     Boolean            tconSpecified = false;        
  271.     Boolean            tagSpecified = false;
  272.     Boolean            cellSpecified = false;
  273.     Boolean            pictFileSpecified = false;
  274.     Boolean            cellWidthSpecified = false;
  275.     Boolean            cellHeightSpecified = false;
  276.     char                *ofile;                /* output file name */
  277.     char                *ifile;                /* input file name */
  278.     short                id;                    /* STR# resource id */
  279.     short                firstID;                /* first STR# resource id */
  280.     short                tconID;                /* TCON resource id */
  281.     short                tagID;                /* TAG resource id */
  282.     short                cellID;                /* CELL resource id */
  283.     char                 *pfile;                /* pict file name */
  284.     short                cellWidth;            /* cell width */
  285.     short                cellHeight;            /* cell height */
  286.     Handle            theRez;                /* handle to STR# resource */
  287.     Handle            tconRez;                /* handle to TCON resource */
  288.     Handle            tagRez;                /* handle to TAG resource */
  289.     Handle            cellRez;                /* handle to CELL resource */
  290.     unsigned char    *pp;                    /* pointer to beginning of cur line
  291.                                                     in STR# rsrc */
  292.     unsigned char    *q;                    /* pointer to cur pos in TCON rsrc */
  293.     unsigned char    *r;                    /* pointer to cur pos in TAG rsrc */
  294.     unsigned char    *t;                    /* pointer to cur pos in CELL rsrc */
  295.     unsigned short    offset;                /* offset of line if STR# resource */ 
  296.     short                strLen;                /* length of STR# line */
  297.     FILE                *input;                /* input file */
  298.     OSErr                rCode;                /* result code */
  299.     short                ofileNum;            /* output file ref num */
  300.     short                pfileNum;            /* pict file ref num */
  301.     short                nlines;                /* number of lines in cur STR# rsrc */
  302.     short                totLines = 0;        /* total number of screen-visible lines */
  303.     short                ntcon;                /* number of tcon entries */
  304.     short                ntag;                    /* number of tag entries */
  305.     char                str[256];            /* line buffer */
  306.     short                len;                    /* length of line */
  307.     unsigned char    *s;                    /* pointer to cur pos in str */
  308.     short                size;                    /* size of resource */
  309.     Boolean            newRez;                /* true if new STR# should be started */
  310.     Boolean            nextStyle = false;    /* true if next line has style */
  311.     Boolean            nextJust = false;    /* true if next line or pict has just */
  312.     Boolean            nextSize = false;    /* true if next line has size multiplier */
  313.     Boolean            nextOnly = false;    /* true if next line or pict has only */
  314.     unsigned char    styleCode;            /* style code for next line */
  315.     unsigned char    justCode;            /* justification code for next line or
  316.                                                     pict */
  317.     short                sizePercent;        /* size percentage for next line */                                                    
  318.     unsigned char    onlyCode;            /* only code for next line or pict */                                                    
  319.     short                picID;                /* pict resource id */
  320.     PicHandle        picHandle;            /* handle to pict */
  321.     short                picWidth;            /* pict width */
  322.     short                picHeight;            /* pict height */
  323.     short                picScaledHeight;    /* pict height after scaling */
  324.     short                picBands;            /* number of bands in scaled pict */
  325.     short                pageNum;                /* page number in \page directive */
  326.     short                xspace;                /* extra space in \itcon directive */
  327.  
  328.     /* Crack and check parameters. */
  329.  
  330.     i = 1;
  331.     while (i < argc) {
  332.         if (*argv[i] == '-') {
  333.             if (tolower(*(argv[i]+1)) == 'o') {
  334.                 outFileSpecified = true;
  335.                 ofile = argv[i+1];
  336.                 i += 2;
  337.             } else if (tolower(*(argv[i]+1)) == 'i') {
  338.                 idSpecified = true;
  339.                 firstID = atoi(argv[i+1]);
  340.                 i += 2;
  341.             } else if (tolower(*(argv[i]+1)) == 't') {
  342.                 tconSpecified = true;
  343.                 tconID = atoi(argv[i+1]);
  344.                 i += 2;
  345.             } else if (tolower(*(argv[i]+1)) == 'g') {
  346.                 tagSpecified = true;
  347.                 tagID = atoi(argv[i+1]);
  348.                 i += 2;
  349.             } else if (tolower(*(argv[i]+1)) == 'c') {
  350.                 cellSpecified = true;
  351.                 cellID = atoi(argv[i+1]);
  352.                 i += 2;
  353.             } else if (tolower(*(argv[i]+1)) == 'p') {
  354.                 pictFileSpecified = true;
  355.                 pfile = argv[i+1];
  356.                 i += 2;
  357.             } else if (tolower(*(argv[i]+1)) == 'w') {
  358.                 cellWidthSpecified = true;
  359.                 cellWidth = atoi(argv[i+1]);
  360.                 i += 2;
  361.             } else if (tolower(*(argv[i]+1)) == 'h') {
  362.                 cellHeightSpecified = true;
  363.                 cellHeight = atoi(argv[i+1]);
  364.                 i += 2;
  365.             } else {
  366.                 fprintf(stderr, "### %s - \"%s\" is not an option.\n",
  367.                     argv[0], argv[i]);
  368.                 return 1;
  369.             };
  370.         } else {
  371.             inFileSpecified = true;
  372.             ifile = argv[i];
  373.             i++;
  374.         };
  375.     };
  376.     if (!outFileSpecified) {
  377.         fprintf(stderr, "### %s - output file not specified.\n", argv[0]);
  378.         return 1;
  379.     };
  380.     if (!idSpecified) {
  381.         fprintf(stderr, "### %s - resource id not specified.\n", argv[0]);
  382.         return 1;
  383.     };
  384.     if (pictFileSpecified && (!cellWidthSpecified || !cellHeightSpecified)) {
  385.         fprintf(stderr, "### %s - when the p option is used the w and h options\n", 
  386.             argv[0]);
  387.         fprintf(stderr, "### must also be specified.\n");
  388.         return 1;
  389.     };
  390.  
  391.     /* Open the input file.  Create it if it doesn't already exist. */
  392.     
  393.     if (!inFileSpecified) {
  394.         input = stdin;
  395.     } else if ((input = fopen(ifile, "r")) == nil) {
  396.         fprintf(stderr, "### %s - unable to open file %s.\n",
  397.             argv[0], ifile);
  398.         return 2;
  399.     };
  400.     
  401.     /* Open the pict file. */
  402.     
  403.     if (pictFileSpecified) {
  404.         pfileNum = openresfile(pfile);
  405.         if (pfileNum == -1) {
  406.             fprintf(stderr, "### %s - unable to open pict file %s.\n",
  407.                 argv[0], pfile);
  408.             return 2;
  409.         };
  410.     };
  411.     
  412.     /* Open the output file. */
  413.     
  414.     SetResLoad(false);
  415.     ofileNum = openresfile(ofile);
  416.     if (ofileNum == -1) {
  417.         createresfile(ofile);
  418.         ofileNum = openresfile(ofile);
  419.         if (ofileNum == -1) {
  420.             fprintf(stderr, "### %s - unable to open or create file %s.\n",
  421.                 argv[0], ofile);
  422.             return 2;
  423.         };
  424.     };
  425.     SetResLoad(true);
  426.     
  427.     /* Get the old TCON resource and increase its size to 32K.  If it
  428.         doesn't exist create a 32K new one. */
  429.         
  430.     if (tconSpecified) {
  431.         if ((tconRez = GetResource('TCON', tconID))  && 
  432.             HomeResFile(tconRez) == ofileNum) {
  433.             SetHandleSize(tconRez, 0x7fff);
  434.             if (rCode = MemError()) {            
  435.                 fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  436.                     argv[0], rCode);
  437.                 return 2;
  438.             };
  439.         } else {
  440.             tconRez = NewHandle(0x7fff);
  441.             if (rCode = MemError()) {            
  442.                 fprintf(stderr, "### %s - error %d on NewHandle.\n",
  443.                     argv[0], rCode);
  444.                 return 2;
  445.             };
  446.             addresource(tconRez, 'TCON', tconID, "");
  447.             if (rCode = ResError()) {            
  448.                 fprintf(stderr, "### %s - error %d on TCON addresource.\n",
  449.                     argv[0], rCode);
  450.                 return 2;
  451.             };
  452.         };
  453.         HLock(tconRez);
  454.         ntcon = 0;
  455.         q = *tconRez + 2;
  456.     };
  457.     
  458.     /* Get the old TAG resource and increase its size to 32K.  If it
  459.         doesn't exist create a 32K new one. */
  460.         
  461.     if (tagSpecified) {
  462.         if ((tagRez = GetResource('TAG ', tagID))  && 
  463.             HomeResFile(tagRez) == ofileNum) {
  464.             SetHandleSize(tagRez, 0x7fff);
  465.             if (rCode = MemError()) {            
  466.                 fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  467.                     argv[0], rCode);
  468.                 return 2;
  469.             };
  470.         } else {
  471.             tagRez = NewHandle(0x7fff);
  472.             if (rCode = MemError()) {            
  473.                 fprintf(stderr, "### %s - error %d on NewHandle.\n",
  474.                     argv[0], rCode);
  475.                 return 2;
  476.             };
  477.             addresource(tagRez, 'TAG ', tagID, "");
  478.             if (rCode = ResError()) {            
  479.                 fprintf(stderr, "### %s - error %d on TAG addresource.\n",
  480.                     argv[0], rCode);
  481.                 return 2;
  482.             };
  483.         };
  484.         HLock(tagRez);
  485.         ntag = 0;
  486.         r = *tagRez + 2;
  487.     };
  488.     
  489.     /* Get the old CELL resource and increase its size to 32K.  If it
  490.         doesn't exist create a 32K new one. */
  491.         
  492.     if (cellSpecified) {
  493.         if ((cellRez = GetResource('CELL', cellID))  && 
  494.             HomeResFile(cellRez) == ofileNum) {
  495.             SetHandleSize(cellRez, 0x7fff);
  496.             if (rCode = MemError()) {            
  497.                 fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  498.                     argv[0], rCode);
  499.                 return 2;
  500.             };
  501.         } else {
  502.             cellRez = NewHandle(0x7fff);
  503.             if (rCode = MemError()) {            
  504.                 fprintf(stderr, "### %s - error %d on NewHandle.\n",
  505.                     argv[0], rCode);
  506.                 return 2;
  507.             };
  508.             addresource(cellRez, 'CELL', cellID, "");
  509.             if (rCode = ResError()) {            
  510.                 fprintf(stderr, "### %s - error %d on CELL addresource.\n",
  511.                     argv[0], rCode);
  512.                 return 2;
  513.             };
  514.         };
  515.         HLock(cellRez);
  516.         t = *cellRez;
  517.     };
  518.     
  519.     /* Main loop.  Create each new STR# resource one at a time. */
  520.     
  521.     id = firstID;
  522.     while (true) {
  523.         
  524.         /*    Get the old STR# resource and increase its size to 32K.  If it
  525.             doesn't exist create a 32K new one. */
  526.         
  527.         if (id-firstID >= 64) {
  528.             fprintf(stderr, "### %s - more than 64 STR# resources.\n",
  529.                 argv[0], rCode);
  530.             return 2;
  531.         };
  532.         if ((theRez = GetResource('STR#', id))  && 
  533.             HomeResFile(theRez) == ofileNum) {
  534.             SetHandleSize(theRez, 0x7fff);
  535.             if (rCode = MemError()) {            
  536.                 fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  537.                     argv[0], rCode);
  538.                 return 2;
  539.             };
  540.         } else {
  541.             theRez = NewHandle(0x7fff);
  542.             if (rCode = MemError()) {            
  543.                 fprintf(stderr, "### %s - error %d on NewHandle.\n",
  544.                     argv[0], rCode);
  545.                 return 2;
  546.             };
  547.             addresource(theRez, 'STR#', id, "");
  548.             if (rCode = ResError()) {            
  549.                 fprintf(stderr, "### %s - error %d on STR# id=%d addresource.\n",
  550.                     argv[0], rCode, id);
  551.                 return 2;
  552.             };
  553.         };
  554.         
  555.         /* Read lines from the input file, convert them to pascal format,
  556.             and append them to the STR# buffer. */
  557.             
  558.         HLock(theRez);
  559.         p = *theRez + 2;
  560.         nlines = 0;
  561.         while (fgets(str, 255, input)) {
  562.             len = strlen(str);
  563.             if (len && *(str+len-1) == '\n') {
  564.                 *(str+len-1) = 0;
  565.                 len--;
  566.             };
  567.             newRez = false;
  568.             if (len && *str == '\\') {
  569.                 if (*(str+len-1) == docEop) {
  570.                     *(str+len-1) = 0;
  571.                     len--;
  572.                 };
  573.                 if (newRez = len >= 5 && !strncmp(str, "\\str#", 5)) break;
  574.                 if (len >= 5 && !strncmp(str, "\\tcon", 5)) {
  575.                     if (!tconSpecified) {
  576.                         fprintf(stderr, "### %s - tcon id not specified.\n",
  577.                             argv[0]);
  578.                         return 2;
  579.                     };
  580.                     *((short*)q) = totLines;
  581.                     q += 2;
  582.                     *q++ = nextOnly ? onlyCode : docScreen | docPrint;
  583.                     nextOnly = false;
  584.                     *q++ = len-6;
  585.                     memcpy(q, str+6, len-6);
  586.                     q += len-6;
  587.                     if ((long)q & 1) q++;
  588.                     ntcon++;
  589.                 } else if (len >= 4 && !strncmp(str, "\\tag", 4)) {
  590.                     if (!tagSpecified) {
  591.                         fprintf(stderr, "### %s - tag id not specified.\n",
  592.                             argv[0]);
  593.                         return 2;
  594.                     };
  595.                     *((short*)r) = totLines;
  596.                     r += 2;
  597.                     *((short*)r) = atoi(str+5);
  598.                     r += 2;
  599.                     ntag++;
  600.                 } else if (len >= 8 && !strncmp(str, "\\style", 6)) {
  601.                     nextStyle = true;
  602.                     styleCode = 0;
  603.                     s = str+6;
  604.                     while (s < str+len) {
  605.                         s += strspn(s, " \t");
  606.                         if (!strncmp(s, "normal", 6)) {
  607.                             styleCode = normal;
  608.                         } else if (!strncmp(s, "bold", 4)) {
  609.                             styleCode |= bold;
  610.                         } else if (!strncmp(s, "italic", 6)) {
  611.                             styleCode |= italic;
  612.                         } else if (!strncmp(s, "underline", 9)) {
  613.                             styleCode |= underline;
  614.                         } else if (!strncmp(s, "outline", 7)) {
  615.                             styleCode |= outline;
  616.                         } else if (!strncmp(s, "shadow", 6)) {
  617.                             styleCode |= shadow;
  618.                         } else if (!strncmp(s, "condense", 8)) {
  619.                             styleCode |= condense;
  620.                         } else if (!strncmp(s, "extend", 6)) {
  621.                             styleCode |= extend;
  622.                         } else {
  623.                             fprintf(stderr, 
  624.                                 "### %s - illegal style option %s.\n",
  625.                                 argv[0], s);
  626.                             return 2;
  627.                         };
  628.                         s += strcspn(s, " \t");
  629.                     };
  630.                 } else if (len >= 7 && !strncmp(str, "\\just", 5)) {
  631.                     nextJust = true;
  632.                     s = str+6;
  633.                     s += strspn(s, " \t");
  634.                     if (!strncmp(s, "left", 4)) {
  635.                         justCode = docLeft;
  636.                     } else if (!strncmp(s, "center", 6)) {
  637.                         justCode = docCenter;
  638.                     } else if (!strncmp(s, "right", 5)) {
  639.                         justCode = docRight;
  640.                     } else {
  641.                         fprintf(stderr, 
  642.                             "### %s - illegal justification option %s.\n",
  643.                             argv[0], s);
  644.                         return 2;
  645.                     };
  646.                 } else if (len >= 7 && !strncmp(str, "\\size", 5)) {
  647.                     nextSize = true;
  648.                     s = str+6;
  649.                     s += strspn(s, " \t");
  650.                     sizePercent = atoi(s);
  651.                 } else if (len >= 7 && !strncmp(str, "\\only", 5)) {
  652.                     nextOnly = true;
  653.                     onlyCode = 0;
  654.                     s = str+6;
  655.                     while (s < str+len) {
  656.                         s += strspn(s, " \t");
  657.                         if (!strncmp(s, "screen", 6)) {
  658.                             onlyCode |= docScreen;
  659.                         } else if (!strncmp(s, "print", 5)) {
  660.                             onlyCode |= docPrint;
  661.                         } else if (!strncmp(s, "save", 4)) {
  662.                             onlyCode |= docSave;
  663.                         } else {
  664.                             fprintf(stderr, 
  665.                                 "### %s - illegal only option %s.\n",
  666.                                 argv[0], s);
  667.                             return 2;
  668.                         };
  669.                         s += strcspn(s, " \t");
  670.                     };
  671.                 } else if (len >= 7 && !strncmp(str, "\\pict", 5)) {
  672.                     if (!pictFileSpecified) {
  673.                         fprintf(stderr, "### %s - picture file not specified.\n",
  674.                             argv[0]);
  675.                         return 2;
  676.                     };
  677.                     s = str+6;
  678.                     s += strspn(s, " \t");
  679.                     picID = atoi(s);
  680.                     picHandle = GetPicture(picID);
  681.                     if (!picHandle) {
  682.                         fprintf(stderr, "### %s - picture id %d not found.\n",
  683.                             argv[0], picID);
  684.                         return 2;
  685.                     };
  686.                     picWidth = (**picHandle).picFrame.right -
  687.                         (**picHandle).picFrame.left;
  688.                     picHeight = (**picHandle).picFrame.bottom -
  689.                         (**picHandle).picFrame.top;
  690.                     ReleaseResource((Handle)picHandle);
  691.                     if (picWidth <= cellWidth-8) {
  692.                         picScaledHeight = picHeight;
  693.                     } else {
  694.                         picScaledHeight = picHeight * (cellWidth-8) / picWidth;
  695.                     };
  696.                     picBands = (picScaledHeight + cellHeight - 1) / cellHeight;
  697.                     for (i = 0; i < picBands; i++) {
  698.                         if (p+13 - *theRez > 0x7f00) {
  699.                             fprintf(stderr, 
  700.                                 "### %s - too much text in STR# resource (>32K).\n", 
  701.                                 argv[0]);
  702.                             return 2;
  703.                         };
  704.                         pp = p;
  705.                         p++;
  706.                         strLen = 6;
  707.                         if (nextJust && justCode != docCenter) {
  708.                             *p++ = docJust;
  709.                             *p++ = 3;
  710.                             *p++ = justCode;
  711.                             strLen += 3;
  712.                         };
  713.                         if (nextOnly && onlyCode != (docScreen + docPrint)) {
  714.                             *p++ = docOnly;
  715.                             *p++ = 3;
  716.                             *p++ = onlyCode;
  717.                             strLen += 3;
  718.                         };
  719.                         *p++ = docPict;
  720.                         *p++ = 6;
  721.                         *p++ = picID >> 8;
  722.                         *p++ = picID & 0xff;
  723.                         *p++ = i >> 8;
  724.                         *p++ = i & 0xff;
  725.                         *pp = strLen;
  726.                         nlines++;
  727.                         if (!nextOnly || (onlyCode & docScreen)) {
  728.                             totLines++;
  729.                             if (cellSpecified) {
  730.                                 *t++ = id-firstID;
  731.                                 offset = pp - *theRez;
  732.                                 *t++ = offset >> 8;
  733.                                 *t++ = offset & 0xff;
  734.                             };
  735.                         };
  736.                     };
  737.                     nextStyle = nextJust = nextSize = nextOnly = false;
  738.                 } else if (len >= 5 && !strncmp(str, "\\page", 5)) {
  739.                     *p++ = 7;
  740.                     putOnlyPrint();
  741.                     s = str+5;
  742.                     s += strspn(s, " \t");
  743.                     pageNum = *s ? atoi(s) : 0xffff;
  744.                     *p++ = docPage;
  745.                     *p++ = 4;
  746.                     *p++ = pageNum >> 8;
  747.                     *p++ = pageNum & 0xff;
  748.                     nlines++;
  749.                 } else if (len >= 5 && !strncmp(str, "\\keep", 5)) {
  750.                     *p++ = 5;
  751.                     putOnlyPrint();
  752.                     *p++ = docKeep;
  753.                     *p++ = 2;
  754.                     nlines++;
  755.                 } else if (len >= 8 && !strncmp(str, "\\endkeep", 8)) {
  756.                     *p++ = 5;
  757.                     putOnlyPrint();
  758.                     *p++ = docEndKeep;
  759.                     *p++ = 2;
  760.                     nlines++;
  761.                 } else if (len >= 8 && !strncmp(str, "\\itcon", 6)) {
  762.                     *p++ = 7;
  763.                     putOnlyPrint();
  764.                     s = str+6;
  765.                     s += strspn(s, " \t");
  766.                     xspace = atoi(s);
  767.                     *p++ = docITcon;
  768.                     *p++ = 4;
  769.                     *p++ = xspace >> 8;
  770.                     *p++ = xspace & 0xff;
  771.                     nlines++;
  772.                 };
  773.             } else {
  774.                 if (p+len+1 - *theRez > 0x7f00) {
  775.                     fprintf(stderr, "### %s - too much text (>32K).\n", 
  776.                         argv[0]);
  777.                     return 2;
  778.                 };
  779.                 pp = p;
  780.                 p++;
  781.                 strLen = len;
  782.                 if (nextStyle && styleCode != normal) {
  783.                     *p++ = docStyle;
  784.                     *p++ = 3;
  785.                     *p++ = styleCode;
  786.                     strLen += 3;
  787.                 };
  788.                 if (nextJust && justCode != docLeft) {
  789.                     *p++ = docJust;
  790.                     *p++ = 3;
  791.                     *p++ = justCode;
  792.                     strLen += 3;
  793.                 };
  794.                 if (nextSize && sizePercent != 100) {
  795.                     *p++ = docSize;
  796.                     *p++ = 4;
  797.                     *p++ = sizePercent >> 8;
  798.                     *p++ = sizePercent & 0xff;
  799.                     strLen += 4;
  800.                 };
  801.                 if (nextOnly && onlyCode != 7) {
  802.                     *p++ = docOnly;
  803.                     *p++ = 3;
  804.                     *p++ = onlyCode;
  805.                     strLen += 3;
  806.                 };
  807.                 memcpy(p, str, len);
  808.                 p += len;
  809.                 *pp = strLen;
  810.                 nlines++;
  811.                 if (!nextOnly || (onlyCode & docScreen)) {
  812.                     totLines++;
  813.                     if (cellSpecified) {
  814.                         *t++ = id-firstID;
  815.                         offset = pp - *theRez;
  816.                         *t++ = offset >> 8;
  817.                         *t++ = offset & 0xff;
  818.                     };
  819.                 };
  820.                 nextStyle = nextJust = nextSize = nextOnly = false;
  821.             };
  822.         };
  823.         
  824.         /* Store the number of lines. */
  825.         
  826.         **(short**)theRez = nlines;
  827.         HUnlock(theRez);
  828.         
  829.         /* Adjust STR# resource size and mark it purgable and changed. */
  830.         
  831.         size = p - *theRez;
  832.         SetHandleSize(theRez, size);
  833.         if (rCode = MemError()) {            
  834.             fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  835.                 argv[0], rCode);
  836.             return 2;
  837.         };
  838.         SetResAttrs(theRez, 0x20);
  839.         ChangedResource(theRez);
  840.         if (rCode = ResError()) {            
  841.             fprintf(stderr, "### %s - error %d on ChangedResource.\n",
  842.                 argv[0], rCode);
  843.             return 2;
  844.         };
  845.         
  846.         /* Increment STR# resource id and loop. */
  847.         
  848.         if (!newRez) break;
  849.         id++;
  850.     };
  851.     
  852.     /* Store the number of tcon entries, adjust the TCON resource size,
  853.         and mark it purgable and changed. */
  854.     
  855.     if (tconSpecified) {
  856.         **((short**)tconRez) = ntcon;
  857.         size = q - *tconRez;
  858.         SetHandleSize(tconRez, size);
  859.         if (rCode = MemError()) {            
  860.             fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  861.                 argv[0], rCode);
  862.             return 2;
  863.         };
  864.         SetResAttrs(tconRez, 0x20);
  865.         ChangedResource(tconRez);
  866.         if (rCode = ResError()) {            
  867.             fprintf(stderr, "### %s - error %d on ChangedResource.\n",
  868.                 argv[0], rCode);
  869.             return 2;
  870.         };
  871.     };
  872.     
  873.     /* Store the number of tag entries, adjust the TAG resource size,
  874.         and mark it purgable and changed. */
  875.     
  876.     if (tagSpecified) {
  877.         **((short**)tagRez) = ntag;
  878.         size = r - *tagRez;
  879.         SetHandleSize(tagRez, size);
  880.         if (rCode = MemError()) {            
  881.             fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  882.                 argv[0], rCode);
  883.             return 2;
  884.         };
  885.         SetResAttrs(tagRez, 0x20);
  886.         ChangedResource(tagRez);
  887.         if (rCode = ResError()) {            
  888.             fprintf(stderr, "### %s - error %d on ChangedResource.\n",
  889.                 argv[0], rCode);
  890.             return 2;
  891.         };
  892.     };
  893.     
  894.     /* Adjust the CELL resource size, and mark it purgable and changed. */
  895.     
  896.     if (cellSpecified) {
  897.         size = t - *cellRez;
  898.         SetHandleSize(cellRez, size);
  899.         if (rCode = MemError()) {            
  900.             fprintf(stderr, "### %s - error %d on SetHandleSize.\n",
  901.                 argv[0], rCode);
  902.             return 2;
  903.         };
  904.         SetResAttrs(cellRez, 0x20);
  905.         ChangedResource(cellRez);
  906.         if (rCode = ResError()) {            
  907.             fprintf(stderr, "### %s - error %d on ChangedResource.\n",
  908.                 argv[0], rCode);
  909.             return 2;
  910.         };
  911.     };
  912.     
  913.     /* Close the output and input files. */
  914.         
  915.     CloseResFile(ofileNum);
  916.     if (pictFileSpecified) CloseResFile(pfileNum);
  917.     if (rCode = ResError()) {            
  918.         fprintf(stderr, "### %s - error %d on CloseResFile.\n",
  919.             argv[0], rCode);
  920.         return 2;
  921.     };
  922.     fclose(input);
  923.     return 0;
  924. };
  925.  
  926.